﻿using Colorful.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

using System.Collections.Specialized;
using Colorful.Database;
using System.Net.Mail;
using System.Net;

namespace Colorful.CMS.Core
{
    #region MailService
    public class MailService : IDisposable
    {
        #region 私有变量
        private SmtpClient _smtpClient = null;
        private string _sendMailUrl = $"{WebService.NodeJsAPIUrl}api/sendmail";
        #endregion

        #region 构造函数
        public MailService(string smtp, string username, string password, int port = 25, bool enableSSL = false)
        {
            this.Connection = new SmtpInfo()
            {
                SMTP = smtp,
                Username = username,
                Password = password,
                Port = port,
                SSL = enableSSL
            };
            //_smtpClient = new SmtpClient();
            //_smtpClient.UseDefaultCredentials = true;
            //_smtpClient.Host = smtp;
            //_smtpClient.Port = port;
            //_smtpClient.EnableSsl = enableSSL;
            //_smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            //_smtpClient.Credentials = new NetworkCredential(username, password);
            //_smtpClient.Timeout = 20000;
        }
        #endregion

        #region 属性
        public SmtpInfo Connection { get; set; }
        #endregion

        #region 发送邮件
        /// <summary>
        /// 同步方式发送邮件
        /// </summary>
        /// <param name="toEmail">要主送的邮件地址</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="body">邮件内容</param>
        /// <param name="from">发件人Email</param>
        /// <param name="fromName">发件人名称</param>
        public void SendMail(string toEmail, string subject, string body, string from, string fromName)
        {
            this.SendMail(this.GetMail(toEmail, subject, body, from, fromName));
        }
        /// <summary>
        /// 同步发送Email
        /// </summary>
        /// <param name="mails">要发送的Email列表</param>
        public async void SendMail(params MailMessage[] mails)
        {
            //foreach (var mail in mails)
            //{
            //    _smtpClient.Send(mail);
            //}

            #region 使用NodeJs API发送
            using (var httpClient = new MyHttpClient())
            {
                var list = new List<string>();
                foreach (var mail in mails)
                {
                    var data = new Dictionary<string, string>();
                    data.Add("db", DbSetting.Database);
                    data.Add("to", mail.To[0].Address);
                    data.Add("subject", mail.Subject);
                    data.Add("body", mail.Body);
                    var result = JsonHelper.Parse<JsonResult>(await httpClient.Post(_sendMailUrl, data));
                    if (!result.succ)
                    {
                        list.Add($"Email：{mail.To[0].Address}, db:{DbSetting.Database}, to:{mail.To[0].Address}, subject:{mail.Subject}, body:{mail.Body}, Error:{result.data}");
                    }
                }
                if (list.Count > 0)
                    throw new Exception(string.Join('\n', list));
            }
            #endregion
        }
        /// <summary>
        /// 异步发送Email
        /// </summary>
        /// <param name="mail">Email对象</param>
        public void SendMailAsync(string toEmail, string subject, string body, string from, string fromName)
        {
            this.SendMailAsync(this.GetMail(toEmail, subject, body, from, fromName));
        }
        /// <summary>
        /// 异步发送Email
        /// </summary>
        /// <param name="mails">要发送的Email列表</param>
        /// <returns></returns>
        public void SendMailAsync(params MailMessage[] mails)
        {
            foreach (var mail in mails)
                _smtpClient.SendAsync(mail, null);
        }
        /// <summary>
        /// 获取Email对象
        /// </summary>
        /// <param name="toEmail">要发送到的Email地址</param>
        /// <param name="subject">Email标题</param>
        /// <param name="body">Email内容</param>
        /// <param name="from">发件人地址</param>
        /// <param name="fromName">发件人名称</param>
        /// <param name="headers">Headers</param>
        /// <returns></returns>
        public MailMessage GetMail(string toEmail, string subject, string body, string from, string fromName, NameValueCollection headers = null)
        {
            var mail = new MailMessage()
            {
                Subject = subject,
                IsBodyHtml = true,
                Body = body
            };
            mail.From = new MailAddress(from, fromName);
            mail.To.Add(toEmail);
            mail.Sender = new MailAddress(from);
            if (headers != null)
            {
                foreach (var key in headers.AllKeys)
                    mail.Headers.Add(key, headers[key]);
            }
            return mail;
        }

        public void Dispose()
        {
            if (_smtpClient != null)
                _smtpClient.Dispose();
        }
        #endregion

        #region CMS邮件发送封装
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="mails">要发送的邮件列表</param>
        public static void SendMail(string sendUser, params Mail[] mails)
        {
            var context = System.Web.HttpContext.Current;
            var mailSetting = WebService.EmailSetting;
            if (string.IsNullOrEmpty(sendUser))
                sendUser = context.GetLang(mailSetting.SenderName, mailSetting.SenderNameEn);
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate (object state)
            {
                var mailList = (Mail[])state;
                using (var mailService = new MailService(mailSetting.SMTP, mailSetting.Username, mailSetting.Password, mailSetting.Port))
                {
                    foreach (var mail in mailList)
                    {
                        try
                        {
                            mailService.SendMail(mail.SendTo, mail.Subject, mail.Body, mailSetting.SenderEmail, sendUser);
                        }
                        catch (Exception ex)
                        {
                            context.WriteError(ex, "Email {0} send fail!", mail.SendTo);
                        }
                    }
                }
            }), mails);
        }
        /// <summary>
        /// 批量发送邮件
        /// </summary>
        /// <param name="mails">要发送的邮件列表</param>
        public static void SendMail(params Mail[] mails)
        {
            SendMail(null, mails);
        }
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="email">Email</param>
        /// <param name="title">标题</param>
        /// <param name="body">内容</param>
        /// <param name="sendUser">发件人</param>
        public static void SendMail(string email, string title, string body, string sendUser = null)
        {
            SendMail(sendUser, new Mail() { SendTo = email, Subject = title, Body = body });
        }
        /// <summary>
        /// 发送Email
        /// </summary>
        /// <param name="email">要发送的Email地址</param>
        /// <param name="mailId">Email模板Id</param>
        /// <param name="replaceCallback">模板内容替换回调</param>
        public static void SendMail(string email, int mailId, Func<string, string> replaceCallback, string sendUser = null)
        {
            var context = System.Web.HttpContext.Current;
            var key = $"#mail_{mailId}";
            var mailTemplate = WebService.CacheService.Get(key, () =>
            {
                using (var db = CMSDbHelper.GetDb())
                {
                    var mail = db.MailTemplates.FirstOrDefault(a => a.Id == mailId);
                    mail.Content = ParseMailContent(mail.Content);
                    return mail;
                }
            }, TimeSpan.FromSeconds(WebService.WebSetting.DataCacheTime));
            mailTemplate.Content = replaceCallback(mailTemplate.Content);
            SendMail(email, mailTemplate.Title, mailTemplate.Content, sendUser);
        }
        /// <summary>
        /// 解析Email模板
        /// </summary>
        /// <param name="mailContent"></param>
        /// <returns></returns>
        public static string ParseMailContent(string mailContent)
        {
            var url = WebService.EmailSetting.Url ?? System.Web.HttpContext.Current.Request.GetDomainUrl();
            return mailContent.Replace("src=\"/", $"src=\"{url}/").Replace("src='/", $"src='{url}/")
                    .Replace("href=\"/", $"href=\"{url}/").Replace("#Url#", url, StringComparison.OrdinalIgnoreCase);
        }
        #endregion
    }
    #endregion

    #region SmtpInfo
    public class SmtpInfo
    {
        public string Username { get; set; }
        public string Password { get; set; }
        public string SMTP { get; set; }
        public int Port { get; set; }
        public bool SSL { get; set; }
    }
    #endregion
}